home *** CD-ROM | disk | FTP | other *** search
Text File | 1986-08-10 | 6.9 KB | 191 lines | [TEXT/EDIT] |
- ;; Here's the MacScheme version of the forward chaining rule based
- ;; search example from _LISP second edition_, by Winston and Horn
- ;; Addison-Wesley, publishers
- ;; Greg Grubbs, Aug. '86 GEnie: G.GRUBBS
-
- ;; first, load in MATCH, the pattern matching function from chapter 17
- (load "match.sch")
- ;; ASSERTIONS is a globally accessible variable which contains our knowledge
- ;; base; inferred conclusions will be added here.
- (set! assertions
- '((bozo is a cheetah)
- (bozo is a parent of sugar)
- (bozo is a parent of billy)
- (sweekums is a penguin)
- (king is a penguin)
- (king is a parent of rex)))
-
- ; add aught to our assertion list
- (define (remember new)
- (cond ((member new assertions) nil)
- (else (set! assertions (cons new assertions))
- new)))
-
- ;; 'recall' comes from problem 18-1
- ;; it finds all assertions which match a given pattern
- ;; try: (recall '(> animal) is a (> type))
- (define (recall pattern)
- (recall1 pattern assertions))
- (define (recall1 pattern assertions)
- (cond ((null? assertions) nil)
- ((match pattern (car assertions) nil)
- (cons (car assertions)
- (recall1 pattern (cdr assertions))))
- (else (recall1 pattern (cdr assertions)))))
-
- ;; limited stream handling routines
- (define (combine-streams s1 s2) (append s1 s2))
- (define (add-to-stream e s) (cons e s))
- (define (first-of-stream s) (car s))
- (define (rest-of-stream s) (cdr s))
- (define (empty-stream? s) (null? s))
- (define (make-empty-stream) nil)
-
- ;;
- (define (filter-assertions pattern initial-a-list)
- (do ((assertions assertions (cdr assertions))
- (a-list-stream (make-empty-stream)))
- ((null? assertions) a-list-stream)
- (let ((new-a-list (match pattern (car assertions) initial-a-list)))
- (cond (new-a-list (set! a-list-stream
- (add-to-stream new-a-list a-list-stream)))))))
-
-
- (define (filter-a-list-stream pattern a-list-stream)
- (cond ((empty-stream? a-list-stream) (make-empty-stream))
- (else (combine-streams
- (filter-assertions pattern (first-of-stream a-list-stream))
- (filter-a-list-stream pattern (rest-of-stream a-list-stream))))))
-
- (define (cascade-through-patterns patterns a-list-stream)
- (cond ((null? patterns) a-list-stream)
- (else (filter-a-list-stream (car patterns)
- (cascade-through-patterns (cdr patterns)
- a-list-stream)))))
-
-
- ;; Dig the nested LETs here; The original procedure uses LET*, which is not
- ;; defined in MacScheme, though other Scheme implementations have it.
- (define (use-rule rule)
- (let ((rule-name (cadr rule))
- (ifs (reverse (cdr (caddr rule))))
- (thens (cdr (cadddr rule))))
- (let
- ((a-list-stream (cascade-through-patterns
- ifs
- (add-to-stream '() (make-empty-stream)))))
- (let
- ((action-stream (feed-to-actions
- rule-name thens a-list-stream)))
- (not (empty-stream? action-stream))))))
- (define (spread-through-actions rule-name actions a-list)
- (do ((actions actions (cdr actions))
- (action-stream (make-empty-stream)))
- ((null? actions) action-stream)
- (let ((action (replace-variables (car actions) a-list)))
- (cond ((remember action)
- (print `(rule ,rule-name says ,@action))
- (set! action-stream (add-to-stream action action-stream)))))))
- (define (print x) (begin (display x) (newline))) ; make it pretty
-
- (define (replace-variables s a-list)
- (cond ((atom? s) s)
- ((equal? (car s) '<)
- (cadr (assoc (pattern-variable s) a-list)))
- (else (cons (replace-variables (car s) a-list)
- (replace-variables (cdr s) a-list)))))
- (define (feed-to-actions rule-name actions a-list-stream)
- (cond ((empty-stream? a-list-stream) (make-empty-stream))
- (else (combine-streams
- (spread-through-actions rule-name
- actions
- (first-of-stream a-list-stream))
- (feed-to-actions rule-name
- actions
- (rest-of-stream a-list-stream))))))
- (define (forward-chain)
- (do ((rules-to-try rules (cdr rules-to-try))
- (progress-made '()))
- ((null? rules-to-try) progress-made)
- (cond ((use-rule (car rules-to-try))
- (set! rules-to-try rules)
- (set! progress-made #!true)))))
-
- ;; here's some o' dem silly rules
- (set! rules
- '((rule identify1
- (if ((> animal) has hair))
- (then ((< animal) is mammal)))
- (rule identify2
- (if ((> animal) gives milk))
- (then ((< animal) is mammal)))
- (rule identify3
- (if ((> animal) has feathers))
- (then ((< animal) is bird)))
- (rule identify4
- (if ((> animal) flies)
- ((< animal) lays eggs))
- (then ((< animal) is bird)))
- (rule identify5
- (if ((> animal) eats meat))
- (then ((< animal) is carnivore)))
- (rule identify6
- (if ((> animal) has pointed teeth)
- ((< animal) has claws)
- ((< animal) has forward eyes))
- (then ((< animal) is carnivore)))
- (rule identify7
- (if ((> animal) is mammal)
- ((< animal) has hoofs))
- (then ((< animal) is ungulate)))
- (rule identify8
- (if ((> animal) is mammal)
- ((< animal) chews cud))
- (then ((< animal) is ungulate)
- ((< animal) is even toed)
- ((< animal) is probably a big ugly cow)))
- (rule identify9
- (if ((> animal) is mammal)
- ((< animal) is carnivore)
- ((< animal) has tawny color)
- ((< animal) has dark spots))
- (then ((< animal) is cheetah)))
- (rule identify10
- (if ((> animal) is mammal)
- ((< animal) is carnivore)
- ((< animal) has tawny color)
- ((< animal) has black stripes))
- (then ((< animal) is tiger)))
- (rule identify11
- (if ((> animal) is ungulate)
- ((< animal) has long neck)
- ((< animal) has long legs)
- ((< animal) has dark spots))
- (then ((< animal) is giraffe)))
- (rule identify12
- (if ((> animal) is ungulate)
- ((< animal) has black stripes))
- (then ((< animal) is zebra)))
- (rule identify13
- (if ((> animal) is bird)
- ((< animal) does not fly)
- ((< animal) has long neck)
- ((< animal) has long legs)
- ((< animal) is black and white))
- (then ((< animal) is ostrich)))
- (rule identify14
- (if ((> animal) is bird)
- ((< animal) does not fly)
- ((< animal) swims)
- ((< animal) is black and white))
- (then ((< animal) is penguin)
- ((< animal) might even be ole herring breath himself)))
- (rule identify15
- (if ((> animal) is bird)
- ((< animal) flies well))
- (then ((< animal) is albatross)))
- (rule identify16
- (if ((> animal) is a (> type))
- ((< animal) is a parent of (> child)))
- (then ((< child) is a (< type))))))
-